package com.kcht.test.rfid;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileReader;
import java.time.LocalDateTime;

@Slf4j
@Component
public class EventProvider {
    @Value("${service.log.path:}")
    private String filePath;
    private FileReader fileReader;
    private Boolean isEventing = false;//是否在事件中

    @PostConstruct
    public void refreshFile() {
        new Thread(() -> {
            while (true) {
                LocalDateTime now = LocalDateTime.now();
                this.loadFile(now);
                closeFile(now);
                try {
                    Thread.sleep(1000 * 60);
                } catch (InterruptedException e) {
                    log.error("", e);
                }
            }
        }).start();
    }

    private  void loadFile(LocalDateTime now) {
        if (this.fileReader == null) {
            if (now.getHour() !=0 && now.getHour()!=23) {  //1-22点才加载文件,0和23两小时释放资源
                this.fileReader = arriveEndOfLine();
            }
        }
    }

    private  void closeFile(LocalDateTime now) {
        if (this.fileReader != null) {
            if (now.getHour() == 0 || now.getHour() == 23) { //最后两个小时，释放资源
                try {
                    synchronized (this) {
                        log.info("准备关闭日志文件");
                        if (this.isEventing) {
                            this.wait();
                        }
                        this.fileReader.close();
                        this.fileReader = null;
                        log.info("关闭日志文件成功");
                    }
                } catch (Exception e) {
                    log.info("", e);
                }
            }
        }
    }

    /**
     * 开启一个新事件,文件加载成功且不在事件中则可开启新事件
     */
    public synchronized boolean isExecuteNewEvent() {
        if (this.fileReader != null&&!this.isEventing) {
            this.isEventing = true;
            return true;
        } else {
            return false;
        }
    }

    /**
     * 执行事件结束，如果想要关闭流可以关闭流
     */
    public synchronized void executeEventEnd() {
        this.isEventing = false;
        this.notify();
    }

    /**
     * 读取一行记录,如果一行记录超过1024会数组越界
     * //todo 自动扩容(目前数组越界与业务并无影响,保证关键行不会出现大于1024即可)
     */
    public synchronized String readLine() {
        if (this.isEventing) {
            int[] datas = new int[1024];
            int k = 0;
            int data;
            try {
                while ((data = this.fileReader.read()) != '\n') {
                    if (data == -1) {
                        break;
                    }
                    datas[k] = data;
                    k++;
                }
            } catch (Exception e) {
                log.info("读取日志文件异常", e);
            }
            if (k == 0) {
                return null;
            } else {
                return new String(datas, 0, k);
            }
        } else {
            throw new RuntimeException("不可在事件外读");
        }
    }

    /**
     * 到达行尾,防止重启后,抓取时间过长
     */
    private  FileReader arriveEndOfLine() {
        File file = new File(this.filePath);
        FileReader fileReaderCopy;
        log.info("加载日志文件");
        try {
            fileReaderCopy = new FileReader(file);
        } catch (FileNotFoundException e) {
            log.error("日志文件加载错误--->", e);
            throw new RuntimeException();
        }
        log.info("开始准备抵达日志文件尾部");
        try {
            while (fileReaderCopy.read() != -1) {
            }
        } catch (Exception e) {
            log.info("读取日志文件异常", e);
        }
        log.info("已抵达日志文件尾部");
        return fileReaderCopy;
    }
}
